package com.gk.panda.apis.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gk.panda.apis.Vo.exports.ExportHandheldVO;
import com.gk.panda.apis.dto.imports.ImportHandheldDTO;
import com.gk.panda.apis.entity.deviceHandheldTerminal.dto.HandheldTerminalDto;
import com.gk.panda.apis.entity.deviceHandheldTerminal.dto.HandheldTerminalListDto;
import com.gk.panda.apis.entity.deviceHandheldTerminal.vo.HandheldTerminalListVo;
import com.gk.panda.apis.mapper.DeviceHandheldTerminalMapper;
import com.gk.panda.apis.service.DeviceHandheldTerminalService;
import com.gk.panda.apis.service.OrgService;
import com.gk.panda.apis.util.ListCopyUtils;
import com.gk.panda.apis.util.excel.ExcelUtils;
import com.gk.panda.commons.constant.Constants;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.commons.util.UserUtil;
import com.gk.panda.pojo.DeviceHandheldTerminal;
import com.gk.panda.pojo.Org;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName: DeviceHandheldTerminalService
 * @Description: 手持终端
 * @author: Sir.yang
 * @date: 2022/11/4 15:08
 * @version: 1.0
 **/
@Service
@Slf4j
public class DeviceHandheldTerminalServiceImpl extends ServiceImpl<DeviceHandheldTerminalMapper, DeviceHandheldTerminal> implements DeviceHandheldTerminalService {

    /**
     * 文件地址
     */
    private static final String TEMPLATE_FILE_NAME = "手持终端导入模板.xlsx";
    /**
     * 文件模板后缀
     */
    private static final String FILE_SUFFIX = ".xlsx";

    @Autowired
    private OrgService orgService;

    /**
     * @description: 获取手持终端列表分页
     * @param: [dto]
     * @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.gk.panda.apis.entity.DeviceHandheldTerminal.vo.HandheldTerminalListVo>
     * @date: 2022/11/4 15:25
     * @version: 1.0
     **/
    @Override
    public Page<HandheldTerminalListVo> getHandheldTerminalList(HandheldTerminalListDto dto) {
        //分页查询
        Page<DeviceHandheldTerminal> page = new Page<>(dto.getPageNumber(),dto.getPageSize());
        //添加查询条件
        QueryWrapper<DeviceHandheldTerminal> wrapper = new QueryWrapper<>();
        wrapper.eq("del_flag", Constants.ZERO);
//        if (null != dto.getOrgId()) {
//            List<Integer> orgIds = dto.getOrgId();
//            List<Integer> list = new ArrayList<>();
//            orgIds.forEach(id -> {
//                List<Integer> ids = orgService.getPuisneOrgIds(id);
//                list.addAll(ids);
//            });
//            List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
//            wrapper.in("org_id", collect);
//        }
        wrapper.in(dto.getOrgId() != null,"org_id",dto.getOrgId());
        if (StringUtils.isNotEmpty(dto.getDeviceName())) {
            wrapper.and(queryWrapper -> {
                queryWrapper.like("device_name", dto.getDeviceName())
                        .or().like("device_sn", dto.getDeviceName())
                        .or().like("device_mode", dto.getDeviceName())
                        .or().like("remark", dto.getDeviceName());
            });
        }
        Page<DeviceHandheldTerminal> terminalPage = baseMapper.selectPage(page, wrapper);
        //转换返回数据
        Page<HandheldTerminalListVo> voPage = new Page<>();
        if(!CollectionUtils.isEmpty(terminalPage.getRecords())){
            List<HandheldTerminalListVo> terminalListVos = terminalPage.getRecords().stream().map(info -> {
                HandheldTerminalListVo vo = new HandheldTerminalListVo();
                BeanUtils.copyProperties(info, vo);
                return vo;
            }).collect(Collectors.toList());
            voPage.setRecords(terminalListVos);
            voPage.setPages(terminalPage.getPages());
            voPage.setCurrent(terminalPage.getCurrent());
            voPage.setSize(terminalPage.getSize());
            voPage.setTotal(terminalPage.getTotal());
        }
        return voPage;
    }

    /**
     * @description: 修改终端设备信息
     * @param: [dto]
     * @return: java.lang.Integer
     * @date: 2022/11/4 15:25
     * @version: 1.0
     **/
    @Override
    public Integer changeHandheldTerminalInfo(HandheldTerminalDto dto) throws UnsupportedEncodingException {
        DeviceHandheldTerminal handheldTerminal = new DeviceHandheldTerminal();
        BeanUtils.copyProperties(dto, handheldTerminal);
        handheldTerminal.setUpdateName(UserUtil.getCurrentUserName());
        handheldTerminal.setFkUpdate(UserUtil.getCurrentUser());
        handheldTerminal.setUpdateTime(new Date());
        return baseMapper.updateById(handheldTerminal);
    }

    /**
     * @description: 新增终端设备信息
     * @param: [dto]
     * @return: java.lang.Integer
     * @date: 2022/11/4 15:25
     * @version: 1.0
     **/
    @Override
    public Integer saveHandheldTerminalInfo(HandheldTerminalDto dto) throws UnsupportedEncodingException {
        DeviceHandheldTerminal handheldTerminal = new DeviceHandheldTerminal();
        BeanUtils.copyProperties(dto, handheldTerminal);
        handheldTerminal.setCreateName(UserUtil.getCurrentUserName());
        handheldTerminal.setFkCreate(UserUtil.getCurrentUser());
        handheldTerminal.setCreateTime(new Date());
        return baseMapper.insert(handheldTerminal);
    }

    /**
     * @description: 删除设备信息
     * @param: [deviceId]
     * @return: java.lang.Integer
     * @date: 2022/11/4 15:25
     * @version: 1.0
     **/
    @Override
    public Integer removeHandheldTerminalInfo(Integer deviceId) throws UnsupportedEncodingException {
        DeviceHandheldTerminal handheldTerminal = new DeviceHandheldTerminal();
        handheldTerminal.setDeviceId(deviceId);
        handheldTerminal.setUpdateName(UserUtil.getCurrentUserName());
        handheldTerminal.setFkUpdate(UserUtil.getCurrentUser());
        handheldTerminal.setUpdateTime(new Date());
        handheldTerminal.setDelFlag(Constants.ONE);
        return baseMapper.updateById(handheldTerminal);
    }


    /**
     * @description: 统计手持终端数量根据机构ID
     * @param: [orgId]
     * @return: java.lang.Integer
     * @date: 2022/11/11 15:17
     * @version: 1.0
     *
     * @param orgIds*/
    @Override
    public Integer getHandheldTerminaCountByOrgId(List<Integer> orgIds) {
        QueryWrapper<DeviceHandheldTerminal> wrapper = new QueryWrapper<>();
        wrapper.eq("del_flag", Constants.ZERO);
        wrapper.in(!CollectionUtils.isEmpty(orgIds),"org_id", orgIds);
        return baseMapper.selectCount(wrapper).intValue();
    }

    /**
     * 下载手持终端导入模板
     *
     * @param response P
     */
    @Override
    public void downloadTemplate(HttpServletResponse response) {
        XSSFWorkbook workbook = getWorkbook();
        XSSFSheet sheet = workbook.getSheetAt(0);
        // 所属机构
        List<Org> orgs = orgService.list();
        String[] names = orgs.stream().map(Org::getName).toArray(String[]::new);
        ExcelUtils.setDropDownBox(sheet, 1, 0, 65535, 0, names, workbook, "机构");

        // 生成文件
        String downloadFileName = "手持终端信息" + FILE_SUFFIX;
        ExcelUtils.download(downloadFileName, workbook, response);
    }

    /**
     * 批量导入手持终端信息
     *
     * @param file P
     * @return R
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importTerminal(MultipartFile file) throws UnsupportedEncodingException {
        InputStream inputStream;
        List<ImportHandheldDTO> resultList;
        try {
            inputStream = file.getInputStream();
            ImportParams params = new ImportParams();
            params.setStartSheetIndex(0);
            params.setSheetNum(1);
            params.setTitleRows(0);
            params.setHeadRows(1);
            resultList = ExcelImportUtil.importExcel(inputStream, ImportHandheldDTO.class, params);
        } catch (Exception e) {
            e.printStackTrace();
            return "failed";
        }
        if (CollectionUtils.isEmpty(resultList)) {
            return "导入数据为空，请检查填入数据！";
        }
        String currentUser = UserUtil.getCurrentUser();
        String currentUserName = UserUtil.getCurrentUserName();
        // 通过机构名称获取机构id
        List<String> names = resultList.stream().map(ImportHandheldDTO::getOrgName).collect(Collectors.toList());
        List<Org> orgList = orgService.list(Wrappers.<Org>lambdaQuery().in(Org::getName, names));
        resultList.forEach(k -> {
            for (Org v : orgList) {
                if (v.getName().equals(k.getOrgName())) {
                    k.setOrgId(v.getId());
                }
            }
            // 用户信息
            k.setFkCreate(currentUser);
            k.setCreateName(currentUserName);
            k.setCreateTime(new Date());
        });
        List<DeviceHandheldTerminal> handheldTerminals = ListCopyUtils.copyListProperties(resultList, DeviceHandheldTerminal::new);
        //校验导入部分是否有重复编号
        List<String> deviceSns = handheldTerminals.stream().map(DeviceHandheldTerminal::getDeviceSn).collect(Collectors.toList());
        Set<String> set = new HashSet<>();
        List<String> collect = deviceSns.stream().filter(x -> !set.add(x)).collect(Collectors.toList());
        if (collect.size() > 0) {
            return "表格有重复编号：" + StringUtils.join(collect,",");
        }
        //校验导入部分和数据库是否有重复编号
        QueryWrapper<DeviceHandheldTerminal> wrapper = new QueryWrapper<>();
        wrapper.in("device_sn",deviceSns);
        wrapper.eq("del_flag",Constants.ZERO);
        List<DeviceHandheldTerminal> list = list(wrapper);
        if (list != null && list.size() > 0) {
            return "与已有编号重复：" + StringUtils.join(list.stream().map(DeviceHandheldTerminal::getDeviceSn).collect(Collectors.toList()),",");
        }
        //导入
        saveBatch(handheldTerminals);
        return "success";

    }

    /**
     * 批量导出手持终端信息
     *
     * @param response P
     */
    @Override
    public void exportTerminal(HttpServletResponse response) {
        // 查询全部数据
        List<DeviceHandheldTerminal> terminals = list(Wrappers.<DeviceHandheldTerminal>lambdaQuery()
                .eq(DeviceHandheldTerminal::getDelFlag, Constants.ZERO)
                .orderByDesc(DeviceHandheldTerminal::getCreateTime));
        if (CollectionUtils.isEmpty(terminals)) {
            throw new ServerException("暂无数据导出！");
        }
        List<ExportHandheldVO> vos = ListCopyUtils.copyListProperties(terminals, ExportHandheldVO::new);
        // 导出
        ExportParams params = new ExportParams();
        params.setSheetName("手持终端信息");
        params.setHeight((short) 15);
        Workbook workbook = ExcelExportUtil.exportBigExcel(params, ExportHandheldVO.class, vos);
        ExcelExportUtil.closeExportBigExcel();
        // 生成文件
        String downloadFileName = "手持终端导出" + FILE_SUFFIX;
        ExcelUtils.download(downloadFileName, workbook, response);
    }


    /**
     * 获取workbook
     *
     * @return XSSFWorkbook
     */
    private XSSFWorkbook getWorkbook() {
        InputStream inputStream;
        XSSFWorkbook workbook;
        try {
            ClassPathResource classPathResource = new ClassPathResource("excels/" + TEMPLATE_FILE_NAME);
            inputStream = classPathResource.getInputStream();
            workbook = new XSSFWorkbook(inputStream);
        } catch (IOException e) {
            throw new ServerException("手持终端导入模板获取异常！");
        }
        return workbook;
    }
}
